package com.sys.midware.assist.utils.date;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.concurrent.TimeUnit;

import org.apache.log4j.Logger;

public class DateThreadUtil {

	private static final Logger logger = Logger.getLogger(DateThreadUtil.class);
	
	public static final long MINUTES_PER_DAY = 60*24;
	
	public static final long MILLSECONDS_PER_DAY = MINUTES_PER_DAY * 60 * 1000;
	
	// 每个线程一个DateFormat
	public static final ThreadLocal<DateFormat> timeFormatter = new ThreadLocal<DateFormat>(){
			public DateFormat initialValue(){
				return new SimpleDateFormat("HH:mm:ss");
			}
		};
	
	public static final ThreadLocal<DateFormat> dayFormatter = new ThreadLocal<DateFormat>(){
		public DateFormat initialValue(){
			return new SimpleDateFormat("yyyy-MM-dd");
		}
	};
	
	public static final ThreadLocal<DateFormat> dateFormatter = new ThreadLocal<DateFormat>(){
		public DateFormat initialValue(){
			return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		}
	};
	
	public static final ThreadLocal<DateFormat> compactFormatter = new ThreadLocal<DateFormat>(){
		public DateFormat initialValue(){
			return new SimpleDateFormat("yyyyMMddHHmmss");
		}
	};
	
	
	/**
	 * 描述： 返回给定时间减去当前时间的差值，以给定时间单位衡量； 
	 *
	 * @param unit
	 * @return
	 */
	public static long getDateDiff(Date date1, Date date2, TimeUnit unit){
		long duration = date1.getTime() - date2.getTime();
		return unit.convert(duration, TimeUnit.MILLISECONDS);
	}
	
	/**
	 * 描述： 获取明日Date对象；
	 *
	 * @return
	 */
	public static Date getTomorrow(){
		Calendar tomorrow = Calendar.getInstance(Locale.CHINA);
		tomorrow.setTimeInMillis(System.currentTimeMillis());
		tomorrow.add(Calendar.DAY_OF_MONTH, 1);
		tomorrow.set(Calendar.HOUR_OF_DAY, 0);
		tomorrow.set(Calendar.MINUTE, 0);
		tomorrow.set(Calendar.SECOND, 0);
		
		return tomorrow.getTime();
	}
	
	public static Date getNextDay(Date date){
		Calendar c = Calendar.getInstance(Locale.CHINA);
		c.setTime(date);
		c.add(Calendar.DAY_OF_MONTH, 1);
		
		return c.getTime();
	}
	
	/**
	 * 返回下一个整点所对应的时间<br>
	 * 如果当前分钟数大于30，则返回下下一个整点所对应的时间
	 * 例如：
	 * <pre>
	 * 当前时间是 10:20:33 返回 11:00:00
	 * 当前时间是 12:30:10 返回 13:00:00
	 * 当前时间是 15:31:10 返回 17:00:00
	 * 当前时间是 17:00:01 返回 18:00:00
	 * </pre>
	 * @return
	 */
	public static Date getNextHour() {
		Calendar c = Calendar.getInstance(Locale.CHINA);
		int hour = c.get(Calendar.HOUR_OF_DAY);
		int min = c.get(Calendar.MINUTE);
		int expectedHour = hour + 1;
		if (min > 30) {
			expectedHour = expectedHour + 1;
		}
		c.set(Calendar.HOUR_OF_DAY, expectedHour);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);

		return c.getTime();
	}

	/**
	 * 描述： 获取当日给定时刻的Date对象；
	 * time格式： HH：mm：ss
	 *
	 * @return
	 * @throws ParseException 
	 */
	public static Date getToday(String time) {
		Calendar today = Calendar.getInstance(Locale.CHINA);
	
		Date t = getTime(time);
		Calendar temp = Calendar.getInstance(Locale.CHINA);
		temp.setTime(t);
		today.set(Calendar.HOUR_OF_DAY, temp.get(Calendar.HOUR_OF_DAY));
		today.set(Calendar.MINUTE, temp.get(Calendar.MINUTE));
		today.set(Calendar.SECOND, temp.get(Calendar.SECOND));

		return today.getTime();
	}
	
	/**
	 * 根据传入的目标时刻点和执行周期，获取离当前时刻最近运行时刻到当前时间的schedule的首次运行时间差，单位分钟；
	 *
	 * @param time   期望执行任务的时刻点； 例如： 00：00：00；
	 * @param period  执行任务的周期；
	 * @return
	 */
	public static long getFirstStart(String time, int period){
		long leftTime = 0;
		long diff = 0;
		
		Date current = new Date();
		Date date = DateThreadUtil.getToday(time);
		
		if(date.before(current)){
			diff = DateThreadUtil.getDateDiff(current, date, TimeUnit.MINUTES);
			double temp = Math.ceil((double)diff/period);
			leftTime = period*(int)temp - diff;
		}else{
			diff = DateThreadUtil.getDateDiff(date, current, TimeUnit.MINUTES);
			double temp = Math.floor((double)diff/period);
			leftTime = diff - period*(int)temp;
		}
		
		return leftTime;
	}
	
	public static Date getYesterday(){
		Calendar today = Calendar.getInstance(Locale.CHINA);
		today.add(Calendar.DAY_OF_MONTH, -1);
		return today.getTime();
	}

	
	private static Date getTime(String time){
		try {
			return timeFormatter.get().parse(time);
		} catch (ParseException e) {
			logger.error("解析time时格式错误！", e);
		}
		return new Date();
	}
	
	public static String formatTime(Date date){
		return timeFormatter.get().format(date);
	}
	
	public static String formatDate(Date date){
		return dateFormatter.get().format(date);
	}
	
	public static String formatCompactDate(Date date){
		return compactFormatter.get().format(date);
	}
	
	public static String formatDay(Date date){
		return dayFormatter.get().format(date);
	}
	
	public static Date parseDate(String str) throws ParseException{
		return dateFormatter.get().parse(str);
	}
	
	public static Date parseCompactDate(String str) throws ParseException{
        return compactFormatter.get().parse(str);
    }

}
